﻿using Commons;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using RMS.Token;
using RMS.WXPayApi;
using RMSIService;
using RMSModel;
using RMSModel.Models;
using RMSModel.VMModels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using WxPayAPI;
using Microsoft.Extensions.Configuration;
using System.Configuration;
using Microsoft.EntityFrameworkCore;

namespace RMS.Controllers
{
    [Route("wx/[action]")]
    [ApiController]
    public class AuthController : ControllerBase
    {

        private readonly WXApiIService service;

        private readonly RMSDB db;
        private IConfiguration configuration;
        public AuthController(WXApiIService service, RMSDB db, IConfiguration configuration) 
        {
            this.service = service;
            this.db = db;
            this.configuration = configuration;
        }
        [HttpPost]
        public ResultType<Dictionary<string, object>> login_by_weixin([FromBody] VMParamEntity param)
        {
            return service.login_by_weixin(param);
        }

        [HttpPost]
        public ResultType<List<goodstype>> GetAllGoodType()
        {
            return service.GetAllGoodType();
        }

        [HttpPost]
        public ResultType<int> GetGoodsCount()
        {
            return service.GetGoodsCount();
        }

        [HttpPost]
        public ResultType<List<goodstype>> GetGoodTypeById(int id)
        {
            return service.GetGoodTypeById(id);
        }

        [HttpPost]
        public ResultType<Dictionary<string, object>> GetGoodByIdPage( int id,int page,int size)
        {
            return service.GetGoodById(id,page,size);
        }

        [HttpPost]
        public ResultType<VMGoods> GetGoodsDetailById(int id)
        {
            return service.GetGoodsDetailById(id);
        }

        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<int> AddOrder([FromBody]VMOrder order,int userId)
        {
            order.shopuserid = userId;
            order.addtime = DateTime.Now;
            return service.AddOrder(order);
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<Dictionary<string, object>> Checkout([FromBody] goods g, int userId)
        {
            return service.Checkout(g,userId);
        }

        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<List<sys_region>> GetRegionById(int parentId)
        {
            return service.GetRegionById(parentId);
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType AddShopAddress(int userId, [FromBody] shopaddress g)
        {
            g.userid = userId;
            return service.AddShopAddress(g);
        }

        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType UpdateShopAddress( [FromBody] shopaddress g)
        {
            return service.UpdateShopAddress(g);
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<List<shopaddress>> GetAllShopAddress(int userId)
        {
            return service.GetAllShopAddress(userId);
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<shopaddress> GetShopAddressById(int id)
        {
            return service.GetShopAddressById(id);
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<Dictionary<string, object>> prepay(int orderId,int userId)
        {
            ResultType<Dictionary<string, object>> result = new ResultType<Dictionary<string, object>>();
            try
            {
                order o = db.orders.Find(orderId);
                if (o == null)
                {
                    result.ResultCode = 1;
                    result.ResultMsg = "订单已取消";
                    return result;
                }
                if (o.orderstatus==1)
                {
                    result.ResultCode = 1;
                    result.ResultMsg = "订单已支付";
                    return result;
                }
                shopuser u = db.shopuser.Find(userId);
                WxPayData data = new WxPayData();

                data.SetValue("body", "test");
                data.SetValue("attach", orderId.ToString());
                data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());
                data.SetValue("total_fee",Convert.ToInt32(o.orderprice * 100) );
                data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                data.SetValue("goods_tag", "test");
                data.SetValue("trade_type", "JSAPI");
                data.SetValue("openid", u.openid);
                data.SetValue("notify_url", configuration.GetConnectionString("notify_url"));
                WxPayData resultq = WxPayApi.UnifiedOrder(data);

                WxPayData jsApiParam = new WxPayData();
                jsApiParam.SetValue("appId", resultq.GetValue("appid"));
                string timestamp = WxPayApi.GenerateTimeStamp();
                jsApiParam.SetValue("timeStamp", timestamp);
                string nonceStr = WxPayApi.GenerateNonceStr();
                jsApiParam.SetValue("nonceStr", nonceStr);
                jsApiParam.SetValue("package", "prepay_id=" + resultq.GetValue("prepay_id"));
                jsApiParam.SetValue("signType", WxPayData.SIGN_TYPE_HMAC_SHA256);
                string sign = jsApiParam.MakeSign().ToUpper();
                jsApiParam.SetValue("paySign", jsApiParam.MakeSign().ToUpper());
                string xml = jsApiParam.ToXml();
                result.Data.Add("appId", resultq.GetValue("appid"));
                result.Data.Add("timeStamp", timestamp);
                result.Data.Add("nonceStr", nonceStr);
                result.Data.Add("package", "prepay_id=" + resultq.GetValue("prepay_id"));
                result.Data.Add("signType", WxPayData.SIGN_TYPE_HMAC_SHA256);
                result.Data.Add("paySign", sign);
            }
            catch (Exception ex)
            {
                result.ResultCode = 1;
                result.ResultMsg = ex.Message;
            }
            return result;
        }
        [HttpPost]
        public async Task<string> GetNotify()
        {
            //获取回调POST过来的xml数据的代码
            Stream stream = HttpContext.Request.Body;
            byte[] buffer = new byte[HttpContext.Request.ContentLength.Value];
            await stream.ReadAsync(buffer, 0, buffer.Length); //.net core 3.1需要用ReadAsync才不会出错
            string xml = System.Text.Encoding.UTF8.GetString(buffer);
            if (string.IsNullOrEmpty(xml))
            {
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>"; //回调失败返回给微信
            }

            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(xml);
                string sign = data.GetValue("sign").ToString();
                string makesign = data.MakeSign().ToUpper();
                if (!sign.Equals(makesign))
                {
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg>签名验证失败</xml>"; //回调失败返回给微信
                }
                int orderid = Convert.ToInt32(data.GetValue("attach"));
                string result_code = data.GetValue("result_code").ToString();
                string wxpayid = data.GetValue("transaction_id").ToString();
                order o = db.orders.Find(orderid);
                o.wxpayorderid = wxpayid;
                o.orderstatus = result_code.Equals("SUCCESS") ? 1 : 0;
                o.paytime = DateTime.Now;
                db.orders.Attach(o);
                db.Entry(o).State = EntityState.Modified;
                //db.Entry(o).Property(p => p.address).IsModified = false;
                //db.Entry(o).Property(p => p.addtime).IsModified = false;
                //db.Entry(o).Property(p => p.city).IsModified = false;
                //db.Entry(o).Property(p => p.consignee).IsModified = false;
                //db.Entry(o).Property(p => p.district).IsModified = false;
                //db.Entry(o).Property(p => p.expressname).IsModified = false;

                //db.Entry(o).Property(p => p.ordersn).IsModified = false;
                //db.Entry(o).Property(p => p.expressprice).IsModified = false;
                //db.Entry(o).Property(p => p.expresssn).IsModified = false;
                //db.Entry(o).Property(p => p.mobile).IsModified = false;
                //db.Entry(o).Property(p => p.orderprice).IsModified = false;
                //db.Entry(o).Property(p => p.shopuserid).IsModified = false;
                //db.Entry(o).Property(p => p.province).IsModified = false;
                db.SaveChanges();

                ///发送邮件提醒
                
                var shopuser = db.shopuser.Find(o.shopuserid);
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append($"<!DOCTYPE html><html><head><meta charset='utf - 8'>  <title>订单详情</title></head><body><div><h3>会员：{shopuser.nickname}已下单</h3><br><table ><thead><tr><th>商品</th> <th>数量</th><th>金额</th></tr></thead><tbody>");
                var data1 = from og in db.ordergoods
                    join g in db.goods on og.goodid equals g.id
                    where og.orderid == orderid
                    select new goods()
                    {
                        name = og.name,
                        goodsellnumber =og.number,
                        price = og.number*g.price
                      };
                foreach (var gooditem in data1)
                {
                    stringBuilder.Append($"<tr><td>{gooditem.name}</td><td>{gooditem.goodsellnumber}</td><td>{gooditem.price}</td></tr>");
                }
                stringBuilder.Append("</tbody></table></div></body></html>");
                string fromAddr = configuration.GetConnectionString("MailFrom");
                string psw =DesEncrypt.Decrypt(configuration.GetConnectionString("PSW")) ;
                string toAddr = configuration.GetConnectionString("toAddr");
                await MailUtils.SendEmailAsync(fromAddr,psw,toAddr,"下单提醒", stringBuilder.ToString()); 

            }
            catch(Exception ex)
            {
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg>"+ex.Message+"</xml>"; //回调失败返回给微信
            }
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg>OK</xml>"; //回调成功返回给微信，避免重复回调
        }
        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<order> GetOrderById(int id)
        {
            return service.GetOrderById(id);
        }

        [ServiceFilter(typeof(WXApiFilter))]
        [HttpPost]
        public ResultType<Dictionary<string,object>> GetOrderByUserId(int Page, int size,int userId)
        {
            return service.GetOrderByUserId(Page, size, userId);
        }

    }
}
